﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WaveEngine.Extensions.ITasks;
using WaveEngine.Framework;
using WaveEngine.Framework.Animation;
using WaveEngine.Framework.Graphics;

namespace WaveEngine.Extensions.Behaviors
{
    public class FadeBehavior : Behavior
    {
        [RequiredComponent]
        private Transform2D transform = null;

        private TimeSpan timer;

        public TimeSpan Duration { get; set; }
        public IEasingFunction EasingFunction { get; set; }
        public float MaxOpacity { get; set; }
        public float MinOpacity { get; set; }

        public event EventHandler FadeEffectFinished;

        public bool IsFadeIn
        {
            get;
            private set;
        }

        public FadeBehavior(TimeSpan duration)
        {
            this.Duration = duration;
            this.MaxOpacity = 1;
            this.MinOpacity = 0;
            this.IsActive = false;
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void Update(TimeSpan gameTime)
        {
            if (this.timer >= this.Duration)
            {
                if (this.IsFadeIn)
                {
                    this.transform.Opacity = this.MaxOpacity;
                }
                else
                {
                    this.transform.Opacity = this.MinOpacity;
                }

                if (this.FadeEffectFinished != null)
                {
                    this.FadeEffectFinished(this, null);
                }

                this.timer = TimeSpan.Zero;
                this.IsFadeIn = !this.IsFadeIn;
                this.IsActive = false;
                return;
            }

            float elapsedTime = (float)(this.timer.TotalSeconds / this.Duration.TotalSeconds);

            if (this.EasingFunction != null)
            {
                elapsedTime = (float)this.EasingFunction.Ease(elapsedTime);
            }

            if (this.IsFadeIn)
            {
                this.transform.Opacity = this.MinOpacity + (this.MaxOpacity - this.MinOpacity) * elapsedTime;
            }
            else
            {
                this.transform.Opacity = this.MinOpacity + (this.MaxOpacity - this.MinOpacity) * (1 - elapsedTime);
            }

            this.timer += gameTime;
        }

        public ITask CreateFadeInTask()
        {
            return this.Owner.Scene.CreateTask(() =>
            {
                var result = this.Owner.Scene.CreateEmptyTask();

                if (this.transform.Opacity != 1)
                {
                    result = this.Owner.Scene.CreateActionTask(() =>
                    {
                        this.IsFadeIn = true;
                        this.timer = TimeSpan.Zero;
                        this.IsActive = true;
                    })
                    .AndWaitConditionActively(() => !this.IsActive);
                }

                return result;
            });
        }

        public ITask CreateFadeOutTask()
        {
            return this.Owner.Scene.CreateTask(() =>
            {
                var result = this.Owner.Scene.CreateEmptyTask();

                if (this.transform.Opacity != 0)
                {
                    result = this.Owner.Scene.CreateActionTask(() =>
                    {
                        this.IsFadeIn = false;
                        this.timer = TimeSpan.Zero;
                        this.IsActive = true;
                    })
                    .AndWaitConditionActively(() => !this.IsActive);
                }

                return result;
            });
        }
    }
}
